/**
 * 
 */
package org.xlab.baseframework.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.xlab.baseframework.annotation.Loggable;
import org.xlab.baseframework.dao.api.ISystemMessageDAO;
import org.xlab.baseframework.domain.ISystemRootUserDomain;
import org.xlab.baseframework.domain.ISystemUserDomain;
import org.xlab.baseframework.domain.SystemMessage;
import org.xlab.baseframework.domain.enumerate.EnumMessageType;
import org.xlab.baseframework.domain.enumerate.EnumReadIndentifying;
import org.xlab.baseframework.domain.view.SystemMessageVO;
import org.xlab.baseframework.exception.ObjectNotFoundException;
import org.xlab.baseframework.exception.PermissionDeniedException;
import org.xlab.baseframework.exception.SystemMessageAlreadyBeenReadException;
import org.xlab.baseframework.exception.SystemMessageNotFoundException;
import org.xlab.baseframework.service.api.ISystemMessageService;

/**
 * 系统消息服务接口实现类
 * 
 * @author MaKuBEX
 * 
 */
@Service
public class SystemMessageServiceImpl implements ISystemMessageService {

	/**
	 * @serialField
	 */
	private static final long serialVersionUID = 3658325527130210343L;
	private static final Logger log = Logger
			.getLogger(SystemMessageServiceImpl.class);

	@Autowired(required = true)
	@Qualifier("bpf_systemMessageDAO")
	private ISystemMessageDAO systemMessageDAO;

	/**
	 * @see org.xlab.baseframework.service.api.IBaseService#convertToVO(org.xlab.baseframework.domain.INormalDomain)
	 */
	public SystemMessageVO convertToVO(SystemMessage entity) {
		return new SystemMessageVO(entity);
	}

	/**
	 * @see org.xlab.baseframework.service.api.IBaseService#convertToVOList(java.util.Collection)
	 */
	public List<SystemMessageVO> convertToVOList(
			Collection<SystemMessage> entityCollection) {
		List<SystemMessageVO> results = new ArrayList<SystemMessageVO>(
				entityCollection.size());
		for (SystemMessage message : entityCollection) {
			results.add(this.convertToVO(message));
		}
		return results;
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#createAlert(java.lang.String,
	 *      java.util.Date, java.util.Date,
	 *      org.xlab.baseframework.domain.ISystemUserDomain)
	 */
	@Loggable
	public void createAlert(String message, Date startDate, Date endDate,
			ISystemUserDomain createdBy) {
		Date current = new Date();
		SystemMessage systemMessage = new SystemMessage();
		systemMessage.setCreatedBy(createdBy.getUserCode());
		systemMessage.setCreatedByName(createdBy.getRealName());
		systemMessage.setCreatedTime(current);
		systemMessage.setLastUpdatedBy(createdBy.getUserCode());
		systemMessage.setLastUpdatedByName(createdBy.getRealName());
		systemMessage.setLastUpdatedTime(current);
		systemMessage.setMessage(message);
		systemMessage.setStartDate(startDate);
		systemMessage.setEndDate(endDate);
		systemMessage.setReadInd(EnumReadIndentifying.N);
		systemMessage.setType(EnumMessageType.ALERT);
		systemMessage.setSerialNumber(UUID.randomUUID().toString());
		this.systemMessageDAO.save(systemMessage);
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#createNotification
	 *      (java.lang.String, java.lang.String,
	 *      org.xlab.baseframework.domain.ISystemUserDomain)
	 */
	@Loggable
	public void createNotification(String message, String destination,
			ISystemUserDomain createdBy) {
		Date current = new Date();
		SystemMessage systemMessage = new SystemMessage();
		systemMessage.setCreatedBy(createdBy.getUserCode());
		systemMessage.setCreatedByName(createdBy.getRealName());
		systemMessage.setCreatedTime(current);
		systemMessage.setDestination(destination);
		systemMessage.setLastUpdatedBy(createdBy.getUserCode());
		systemMessage.setLastUpdatedByName(createdBy.getRealName());
		systemMessage.setLastUpdatedTime(current);
		systemMessage.setMessage(message);
		systemMessage.setReadInd(EnumReadIndentifying.N);
		systemMessage.setType(EnumMessageType.NOTIFITION);
		systemMessage.setSerialNumber(UUID.randomUUID().toString());
		this.systemMessageDAO.save(systemMessage);
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#createNotifications
	 *      (java.lang.String, java.util.Collection,
	 *      org.xlab.baseframework.domain.ISystemUserDomain)
	 */
	@Loggable
	public void createNotifications(String message,
			Collection<String> destination, ISystemUserDomain createdBy) {
		String sn = UUID.randomUUID().toString();
		Date current = new Date();
		for (String dest : destination) {
			SystemMessage systemMessage = new SystemMessage();
			systemMessage.setCreatedBy(createdBy.getUserCode());
			systemMessage.setCreatedByName(createdBy.getRealName());
			systemMessage.setCreatedTime(current);
			systemMessage.setDestination(dest);
			systemMessage.setLastUpdatedBy(createdBy.getUserCode());
			systemMessage.setLastUpdatedByName(createdBy.getRealName());
			systemMessage.setLastUpdatedTime(current);
			systemMessage.setMessage(message);
			systemMessage.setReadInd(EnumReadIndentifying.N);
			systemMessage.setType(EnumMessageType.NOTIFITION);
			systemMessage.setSerialNumber(sn);
			this.systemMessageDAO.save(systemMessage);
		}
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#deleteNotifications
	 *      (java.lang.String, org.xlab.baseframework.domain.ISystemUserDomain)
	 */
	@Loggable
	public void deleteNotifications(String sn, ISystemUserDomain deletedBy)
			throws SystemMessageNotFoundException, PermissionDeniedException {
		List<SystemMessage> messages = this.findAllBySerialNumber(sn);
		if (!messages.get(0).getCreatedBy()
				.equalsIgnoreCase(deletedBy.getUserCode())
				&& !(deletedBy instanceof ISystemRootUserDomain)) {
			log.warn("User[" + deletedBy.getUserCode()
					+ "] wants to delete message with sn[" + sn
					+ "] without authorized");
			throw new PermissionDeniedException(
					"You can not delete these messages!");
		} else {
			this.systemMessageDAO.removeAll(messages);
		}
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#deleteSystemMessage
	 *      (java.lang.Long, org.xlab.baseframework.domain.ISystemUserDomain)
	 */
	@Loggable
	public void deleteSystemMessage(Long id, ISystemUserDomain deletedBy)
			throws SystemMessageNotFoundException, PermissionDeniedException {
		SystemMessage message = this.findById(id);
		if (!message.getDestination().equalsIgnoreCase(deletedBy.getUserCode())
				&& !(deletedBy instanceof ISystemRootUserDomain)) {
			log.warn("User[" + deletedBy.getUserCode()
					+ "] wants to delete message[" + id
					+ "] without authorized");
			throw new PermissionDeniedException(
					"You can not delete this message!");
		} else {
			this.systemMessageDAO.remove(message);
		}
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#findAllByCreatedBy
	 *      (java.lang.String)
	 */
	public List<SystemMessage> findAllByCreatedBy(String createdBy)
			throws SystemMessageNotFoundException {
		try {
			return this.systemMessageDAO.findAllByProperty("createdBy",
					createdBy);
		} catch (ObjectNotFoundException e) {
			log.debug("No more message found by createdBy[" + createdBy + "]");
			throw new SystemMessageNotFoundException(e);
		}
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#findAllByDestination(java.lang.String)
	 */
	public List<SystemMessage> findAllByDestination(String destination)
			throws SystemMessageNotFoundException {
		try {
			return this.systemMessageDAO.findAllByProperty("destination",
					destination);
		} catch (ObjectNotFoundException e) {
			log.debug("No more message found by destination[" + destination
					+ "]");
			throw new SystemMessageNotFoundException(e);
		}
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#
	 *      findAllBySerialNumber(java.lang.String)
	 */
	public List<SystemMessage> findAllBySerialNumber(String serialNumber)
			throws SystemMessageNotFoundException {
		try {
			return this.systemMessageDAO.findAllByProperty("serialNumber",
					serialNumber);
		} catch (ObjectNotFoundException e) {
			log.debug("No more message found by serialNumber[" + serialNumber
					+ "]");
			throw new SystemMessageNotFoundException(e);
		}
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#findById(java
	 *      .lang.Long)
	 */
	public SystemMessage findById(Long id)
			throws SystemMessageNotFoundException {
		try {
			return this.systemMessageDAO.findById(id);
		} catch (ObjectNotFoundException e) {
			log.debug("Can not find system message by id[" + id + "]");
			throw new SystemMessageNotFoundException(e);
		}
	}

	/**
	 * @return the systemMessageDAO
	 */
	public ISystemMessageDAO getSystemMessageDAO() {
		return systemMessageDAO;
	}

	/**
	 * @see org.xlab.baseframework.service.api.ISystemMessageService#markRead(java.lang.Long,
	 *      org.xlab.baseframework.domain.ISystemUserDomain)
	 */
	@Loggable
	public void markRead(Long id, ISystemUserDomain updatedBy)
			throws SystemMessageNotFoundException,
			SystemMessageAlreadyBeenReadException, PermissionDeniedException {
		SystemMessage message = this.findById(id);
		if (message.getReadInd() == EnumReadIndentifying.Y) {
			log.debug("Message[" + id
					+ "] read indentifying has been set to Y already!");
			throw new SystemMessageAlreadyBeenReadException();
		} else {
			if (!message.getDestination().equalsIgnoreCase(
					updatedBy.getUserCode())
					&& !(updatedBy instanceof ISystemRootUserDomain)) {
				log.warn("User[" + updatedBy.getUserCode()
						+ "] wants to mark message[" + id
						+ "] without authorized");
				throw new PermissionDeniedException(
						"You can not mark this message read!");
			} else {
				message.setReadInd(EnumReadIndentifying.Y);
				message.setLastUpdatedBy(updatedBy.getUserCode());
				message.setLastUpdatedByName(updatedBy.getRealName());
				message.setLastUpdatedTime(new Date());
				this.systemMessageDAO.update(message);
			}
		}
	}

	/**
	 * @see org.xlab.baseframework.service.api.IBaseService#parseFromVO(org.xlab.baseframework.domain.view.IViewDomainObject)
	 */
	public SystemMessage parseFromVO(SystemMessageVO viewObject) {
		SystemMessage pojo = new SystemMessage();
		BeanUtils.copyProperties(viewObject, pojo);
		return pojo;
	}

	/**
	 * @param systemMessageDAO
	 *            the systemMessageDAO to set
	 */
	public void setSystemMessageDAO(ISystemMessageDAO systemMessageDAO) {
		this.systemMessageDAO = systemMessageDAO;
	}

}
